#include "MeshStructure.hpp"

namespace Model {

std::list<MeshData *> MeshData::_caches;

MeshData::MeshData() : indices() {}

MeshData::~MeshData() {
  indices.clear();
  _buffer.clear();
  _format.clear();
  _vert_count = 0;
}

std::shared_ptr<MeshData> MeshData::CreateMeshData() {
  auto *meshData = new MeshData();
  _caches.push_back(meshData);
  return std::shared_ptr<MeshData>(meshData);
}

void MeshData::RemoveMesh(const std::shared_ptr<MeshData> &ref) {
  _caches.remove_if([&ref](MeshData *&p) -> bool {
    if (ref == std::shared_ptr<MeshData>(p)) {
      delete p;
      p = nullptr;
      return true;
    }
    return false;
  });
}

void MeshData::RemoveAll() {
  for (auto &val : _caches) {
    if (val) {
      delete val;
      val = nullptr;
    }
  }
  _caches.clear();
}

void MeshData::Assign(const std::vector<float> &data,
                      const std::vector<VertexAttribFormat> &vertFormat) {
  _buffer = std::move(data);
  _format = std::move(vertFormat);
  uint8_t sum = 0;
  for (const auto &val : _format) {
    sum += GetAttribTypeComp(val.type);
  }
  _vert_count = _buffer.size() / sum;
}

void MeshData::SortFormat() {
  if (!_format.empty()) {
    std::sort(_format.begin(), _format.end(),
              [](const VertexAttribFormat &a, const VertexAttribFormat &b) -> bool {
                if (int(a.type) < int(b.type)) {
                  return true;
                }
                return false;
              });
  }
}

void MeshData::AssignIndex(const std::vector<uint32_t> &data) {
  indices = std::move(data);
}

} // namespace Model